/**
 * Created with JetBrains WebStorm.
 * User: Administrator
 * Date: 14-1-21
 * Time: 上午10:25
 * To change this template use File | Settings | File Templates.
 */
define(function(require,exports,module){
    var VERSION = "1.0.0",
        jquery = $ = require("jquery-1.8.2.min.js");

    var defaults = {
        width:'auto',
        height:'280px',
        cols:[],
        url:false,
        params:{},
        method:'POST',
        cache:false,
        root:'items',
        items:[],
        autoLoad:true,
        remoteSort:false,
        sortName:'',
        sortStatus:'asc',
        loadingText:'正在载人...',
        noDataText:'没有数据..',
        loadErrorText:'数据加载出现异常',
        multiSelect:false,
        checkCol:false,
        indexCol:false,
        indexColWidth:30,
        fullWidthRows:false,
        nowrap:false,
        showBackboard:true,
        backboardMinHeight:125,
        plugins:[]
    };

    var MMGrid = function(element,options){
        this._id =(((1 + Math.random()) * 0x10000) | 0).toString(16);
        this._loadCount = 0;
        this.opts = options;

        this._initLayout($(element));
        this._initHead();
        this._initOptions();
        this._initEvents();
        this._setColsWidth();

        if(this.opts.fullWidthRows){
            //todo fullWidthRows
        }

        if(options.autoLoad){
            var that = this;
            this.opts = options;
            setTimeout(function(){
                if(options.url){
                    that.load()
                }else{
                    that.load(options.items)
                }
            },0)
        }
    };
    MMGrid.prototype = {
        _initLayout:function($el){
            var opts = this.opts;
            var $elParent = $el.parent();
            var elIndex = $el.index();
            var mmGrid = [
                '<div class="mmGrid">',
                '<style></style>',
                '<div class="mmg-headWrapper">',
                '<table class="mmg-head" cellspacing="0"></table>',
                '</div>',
                '<div class="mmg-colResizePointer"></div>',
                '<div class="mmg-colResizePointer-before"></div>',
                '<div class="mmg-backboard">',
                '<a class="mmg-btnBackboardUp"></a>',
                '</div>',
                '<div class="mmg-bodyWrapper"></div>',
                '<a class="mmg-btnBackboardDn"></a>',
                '<div class="mmg-message">'+ this.opts.noDataText +'</div>',
                '<div class="mmg-mask mmg-transparent"></div>',
                '<div class="mmg-loading">',
                '<div class="mmg-loadingImg"></div>',
                '<div class="mmg-loadingText">'+ this.opts.loadingText +'</div>',
                '</div>',
                '</div>'
            ];
            var $mmGrid = $(mmGrid.join(''));
            this.$mmGrid = $mmGrid;
            this.$style = $mmGrid.find('style');
            this.$headWrapper = $mmGrid.find('.mmg-headWrapper');
            this.$head = $mmGrid.find('.mmg-head');
            this.$backboard = $mmGrid.find('.mmg-backboard');
            this.$bodyWrapper = $mmGrid.find('.mmg-bodyWrapper');
            this.$body = $el.removeAttr('style').addClass('mmg-body');
            this.$body.appendTo(this.$bodyWrapper);

            if(elIndex === 0 || $elParent.children().length == 0){
                $elParent.prepend(this.$mmGrid);
            }else{
                $elParent.children().eq(elIndex-1).after(this.$mmGrid);
            }

            $mmGrid.width(opts.width);
            $mmGrid.height(opts.height);
            if(opts.checkCol){
                var chkHtml = opts.multiSelect ? '<input type = "checkbox" class="checkAll">'
                    : '<input type="checkbox" disabled="disabled" class="checkAll">';

                var a = opts.cols.unshift({title:chkHtml,width:20,align:"center",lockWidth:true,indexCol:true,renderer:function(val,item,rowIndex){
                    return '<label class="mmg-index">'+(rowIndex+1)+'</label>';
                }})
            }
            if(opts.indexCol){
                opts.cols.unshift({
                    title:"#",
                    width:opts.indexColWidth,
                    align:"center",
                    lockWidth:true,
                    indexCol:true,
                    renderer:function(val,item,rowIndex){
                        return '<label class="mmg-index">'+(rowIndex+1)+'</label>'
                    }
                });
            }
        },
        _initHead:function(){
            var that = this;
            var opts = this.opts;
            var $head = this.$head;

            if(opts.cols){
                var theadHtmls = ['<thead>'];
                var titleDeep = that._titleDeep(opts.cols);
                for(var deep = 1;deep<=titleDeep;deep++){
                    var cols = that._colsWithTitleDeep(opts.cols,deep);
                    theadHtmls.push('<tr>');
                    for(var colIndex = 0;colIndex<cols.length;colIndex++){
                        var col = cols[colIndex];
                        theadHtmls.push(this._titleHtml(col,titleDeep-deep+1));
                    }
                    theadHtmls.push('</tr>')
                }
                theadHtmls.push('</thead>');
                $head.html(theadHtmls.join(''));
            }

            var $ths = this._expandThs();
            var expandCols = this._expandCols(opts.cols);

            $.each($ths,function(index){
                if(!expandCols[index].width){
                    expandCols[index].width = 100;
                }
                $.data(this,'col-width',expandCols[index].width);
                $.data(this,'col',expandCols[index]);
            });

            var $mmGrid = this.$mmGrid;
            var $headWrapper = this.$headWrapper;
            var $bodyWrapper = this.$bodyWrapper;
            if(opts.height!=='auto'){
                $bodyWrapper.height($mmGrid.height() - $headWrapper.outerHeight(true));
            }
            if(opts.sortName){
                for(var colIndex=0;colIndex<expandCols.length;colIndex++){
                    var col = expandCols[colIndex];
                    if(col.sortName === opts.sortName || col.name === opts.sortName){
                        var $th = $ths.eq(colIndex);
                        $.data($th.find('.mmg-title')[0],'sortStatus',opts.sortStatus);
                        $th.find('.mmg-sort').addClass('mmg-'+opts.sortStatus);
                    }
                }
            }
        },
        _initOptions:function(){
            var opts = this.opts;
            var $mmGrid = this.$mmGrid;
            var $headWrapper = this.$headWrapper;
            var $backboard = this.$backboard;
            $mmGrid.find('a.mmg-btnBackboardDn').css({
                'top': $headWrapper.outerHeight(true)
            }).slideUp('fast');

            var cols = this._leafCols();
            if(cols){
                var bbHtml = ['<h1>显示列</h1>'];
                for(var colIndex=0; colIndex<cols.length; colIndex++){
                    bbHtml.push('<label ');
                    if(cols[colIndex].checkCol || cols[colIndex].indexCol){
                        bbHtml.push('style="display:none;" ');
                    }
                    var col = cols[colIndex];
                    bbHtml.push('><input type="checkbox"  ');
                    if(!col.hidden) bbHtml.push('checked="checked"');
                    if(col.lockDisplay) bbHtml.push(' disabled="disabled"');
                    bbHtml.push('/><span>');
                    if(col.title){
                        bbHtml.push(col.title);
                    }else{
                        bbHtml.push('未命名');
                    }

                    bbHtml.push('</span></label>');
                }
                $backboard.append($(bbHtml.join('')));
            }
        },
        _initEvents:function(){
            var that = this;
            var opts = this.opts;
            var $mmGrid = this.$mmGrid;
            var $headWrapper = this.$headWrapper;
            var $head = this.$head;
            var $bodyWrapper = this.$bodyWrapper;
            var $body = this.$body;
            var $backboard = this.$backboard;
            var $ths = this._expandThs();
            var expandCols = this._expandCols(opts.cols);
            var leafCols = this._leafCols();

            if(opts.width === 'auto' || opts.height === 'auto' || (typeof opts.width === 'string' && opts.width.indexOf('%') === opts.width.length-1) ||
                typeof opts.height === 'string' && opts.height.indexOf('%') === opts.height.length-1){
                $(window).on('resize', function(){
                    //       that.resize();
                });
            }

            $bodyWrapper.on('scroll',function(){
                $head.css('left',-$(this).scrollLeft());
            });

            var $btnBackboardDn = $mmGrid.find('a.mmg-btnBackboardDn').on('click',function(){
                var backboardHeight = $mmGrid.height() - $headWrapper.outerHeight(true);
                if(opts.height === 'auto' && opts.backboardMinHeight!=='auto' && backboardHeight < opts.backboardMinHeight) {
                    backboardHeight = opts.backboardMinHeight;
                }
                $backboard.height(backboardHeight);
                if(opts.height === 'auto'){
                    $mmGrid.height($headWrapper.outerHeight(true) + $backboard.outerHeight(true));
                }
                $backboard.slideDown();
                $btnBackboardDn.slideUp('fast');
                that_hideMessage();
            });
            $body.on('mouseenter',function(){
                $btnBackboardDn.slideUp('fast');
            });
            $mmGrid.on('mouseleave',function(){
                $btnBackboardDn.slideUp('fast');
            });
            $headWrapper.on('mouseenter',function(){
                if($backboard.is(':hidden') && opts.showBackboard){
                    $btnBackboardDn.slideDown('fast');
                }
            });
            $mmGrid.find('a.mmg-btnBackboardUp').on('click',function(){
                $backboard.slideUp().queue(function(next){
                    if(!that.rowsLength() || (that.rowsLength() === 1 && $body.find('tr.emptyRow').length === 1)){
//                        that._showNoData();
                    }
                    if(opts.height === 'auto'){
                        $mmGrid.height('auto');
                    }
                    next();
                });
            });
            $backboard.on('click',':checkbox',function(){
                var index = $backboard.find('label').index($(this).parent());
                //最后一个不隐藏
                var last = 1;
                if(opts.checkCol){
                    last = last + 1;
                }
                if(opts.indexCol){
                    last = last + 1;
                }
                if($backboard.find('label :checked').length < last){
                    this.checked = true;
                    return;
                }

                var col = leafCols[index];
                if(this.checked){
                    col.hidden = false;

                }else{
                    col.hidden = true;
                }

                var $ths = $head.find('th');
                for(var colIndex=$ths.length-1; colIndex>=0; colIndex--){
                    var $th = $ths.eq(colIndex);
                    var iCol = $th.data('col');
                    if(iCol.cols){
                        var hidden = true;
                        var colspan = 0;
                        $.each(iCol.cols,function(index,item){
                            if(!item.hidden){
                                hidden = false;
                                colspan++;
                            }
                        });
                        //IE bug
                        if(colspan !== 0){
                            $th.prop('colspan',colspan);
                        }
                        iCol.hidden = hidden;
                    }
                }

                that._setColsWidth();
                $backboard.height($mmGrid.height() - $headWrapper.outerHeight(true));
                if(opts.height !== 'auto'){
                    $bodyWrapper.height($mmGrid.height() - $headWrapper.outerHeight(true));
                }
                $mmGrid.find('a.mmg-btnBackboardDn').css({
                    'top': $headWrapper.outerHeight(true)
                })
            });

            $head.on('click','.mmg-title',function(){
                var $this = $(this);
                var $titles = $ths.find('.mmg-title');

                var col = $this.parent().parent().data('col');
                if(!col.sortable){
                    return;
                }
                var sortStatus = $.data(this,'sortStatus') === 'asc' ? 'desc' : 'asc';
                $.each($titles,function(){
                    $.removeData(this,'sortStatus');
                });
                $ths.find('.mmg-sort').removeClass('mmg-asc').removeClass('mmg-desc');
                $.data(this,'sortStatus',sortStatus);
                $this.siblings('.mmg-sort').addClass('mmg-'+sortStatus);

                if(opts.url && opts.remoteSort){
                    that.load()
                }else{
                    that._nativeSorter($.inArray(col,leafCols),sortStatus);
                    that._setStyle();
                }
                //todo resize
            }).on('mousedown','.mmg-colResize',function(e){

                });

            var $body = this.$body;
            $body.on('click','td',function(e){
                var $this = $(this);
                if(!$this.parent().hasClass('selected')){
                    that.select($this.parent().index());
                }else{
                    that.deselect($this.parent().index());
                }
            });
            $body.on('click','tr>td .mmg-check',function(e){
                e.stopPropagation();
                var $this = $(this);
                if(this.checked){
                    that.select($($this.parents('tr')[0]).index());
                }else{
                    that.deselect($($this.parents('tr')[0]).index());
                }
            });
            if(opts.checkCol){
                $head.find('th .checkAll').on('click',function(){
                    if(this.checked){
                        that.select('all');
                    }else{
                        that.deselect('all');
                    }
                })
            }
        },
        _setColsWidth:function(){
            var opts = this.opts;
            var $style = this.$style;
            var $head = this.$head;

            var $bodyWrapper = this.$bodyWrapper;
            var $body = this.$body;
            var $ths = this._expandThs();
            var expandCols = this._expandCols(opts.cols);

            var scrollTop = $bodyWrapper.scrollTop();
            var scrollLeft = $head.position().left;

            $bodyWrapper.width(9999);
            $body.width('auto');
            var styleText = [];
            for(var colIndex=0; colIndex<$ths.length; colIndex++){
                var $th = $ths.eq(colIndex);
                styleText.push('.mmGrid .'+this._genColClass(colIndex) + ' {');
                var width = $.data($th[0],'col-width');
                styleText.push('width: '+ width +'px;');
                styleText.push('max-width: '+ width +'px;');

                var col = expandCols[colIndex];
                if(col.align){
                    styleText.push('text-align: '+col.align+';');
                }
                if(col.hidden){
                    styleText.push('display: none; ');
                }
                styleText.push(' }');
            }
            $body.detach();
            try{
                $style.text(styleText.join(''));
            }catch(error){
                $style[0].styleSheet.cssText = styleText.join('');
            }
            $body.width($head.width());
            $bodyWrapper.width('100%');
            $bodyWrapper.append($body);

            $bodyWrapper.scrollLeft(-scrollLeft);
            if($bodyWrapper.scrollLeft()===0){
                $head.css('left',0);
            }
            $bodyWrapper.scrollTop(scrollTop);
        },
        _nativeSorter:function(colIndex,sortStatus){
            var leafCols = this._leafCols();
            var col = leafCols[colIndex];
            /*this.$body.find('tr>td:nth-child('+(colIndex+1)+')')
                //todo sortElements
                .sortElements(function(a,b){
                    var av = $.text($(a));
                    var bv = $.text($(b));

                    if(col.type === 'number'){
                        av = parseFloat(av);
                        bv = parseFloat(bv)
                    }else{
                        //todo localeCompare
                        return sortStatus === 'desc' ? -av.localeCompare(bv) : av.localeCompare(bv);
                    }
                    return av>bv ? (sortStatus === 'desc' ? -1 : 1) : (sortStatus === 'desc' ? 1 : -1)
                },function(){
                    return this.parentNode;
                })*/
        },
        _titleDeep:function(cols){
            var deep = 1;
            for(var colIndex = 0;colIndex<cols.length;colIndex++){
                var col = cols[colIndex];
                if(col.cols){
                    var newDeep = 1+this._titleDeep(col.cols);
                    if(deep<newDeep){
                        deep = newDeep;
                    }
                }
            }
            return deep;
        },
        _colsWithTitleDeep:function(cols,deep){
            var newCols = [];
            if(!cols){
                return newCols;
            }
            for(var colIndex = 0;colIndex<cols.length;colIndex++){
                var col = cols[colIndex];
                if(deep === 1){
                    newCols.push(col);
                }else{
                    newCols.push.apply(newCols,this._colsWithTitleDeep(col.cols,deep-1));
                }
            }
            return newCols;
        },
        _titleHtml:function(col,rowspan){
            var opts = this.opts;
            var titleHtml = [];
            if(!col.cols){
                titleHtml.push('<th class="');
                var colIndex = $.inArray(col,this._expandCols(opts.cols));
                titleHtml.push(this._genColClass(colIndex));
                titleHtml.push('"');
                titleHtml.push(' rowspan="');
                titleHtml.push(rowspan);
                titleHtml.push('" colspan="');
                titleHtml.push(1);
                titleHtml.push('" data-colIndex="');
                titleHtml.push(colIndex);
                titleHtml.push('">');
                titleHtml.push('<div class="mmg-titleWrapper">');
                titleHtml.push('<span class="mmg-title ');
                if(col.sortable) titleHtml.push('mmg-canSort');
                titleHtml.push('">');
                if(col.titleHtml){
                    titleHtml.push(col.titleHtml);
                }else{
                    titleHtml.push(col.title);
                }
                titleHtml.push('</span><div class="mmg-sort"></div>');
                if(!col.lockWidth){
                    titleHtml.push('<div class="mmg-colResize"></div>');
                }
                titleHtml.push('</div></th>')
            }else{
                var displayColsLength = col.cols.length;
                $.each(col.cols,function(index,item){
                    if(item.hidden){
                        displayColsLength--
                    }
                });

                if(displayColsLength === 0){
                    col.hidden = true;
                }

                titleHtml.push('<th class="');
                var colIndex = $.inArray(col,this._expandCols(opts.cols));
                titleHtml.push(this._genColClass(colIndex));
                titleHtml.push(' mmg-groupCol"');
                titleHtml.push(' rowspan="');
                titleHtml.push(rowspan-1);
                titleHtml.push('" colspan="');
                titleHtml.push(displayColsLength);
                titleHtml.push(' "data-colIndex="');
                titleHtml.push(colIndex);
                titleHtml.push('">');
                titleHtml.push('<div class="mmg-titleWrapper" >');
                titleHtml.push('<span class="mmg-title" ');
                if(col.sortable) titleHtml.push('mmg-canSort');
                titleHtml.push('">');
                if(col.titleHtml){
                    titleHtml.push(col.titleHtml)
                }else{
                    titleHtml.push(col.title);
                }
                titleHtml.push('</span><div class="mmg-sort"></div>');
                titleHtml.push('</div></th>');
            }
            return titleHtml.join("");
        },
        _expandCols:function(cols){
            var newCols = [];
            if(!cols){
                return newCols;
            }
            for(var colIndex = 0;colIndex<cols.length;colIndex++){
                var col = cols[colIndex];
                if(col.cols){
                    newCols.push(col);
                    newCols.push.apply(newCols,this._expandCols(col.cols));
                }else{
                    newCols.push(col);
                }
            }
            return newCols;
        },
        _genColClass:function(colIndex){
            return 'mmg'+this._id+'-col'+colIndex;
        },
        _expandThs:function(){
            return this.$head.find('th').sort(function(a,b){
                return parseInt($(a).data('colindex')) - parseInt($(b).data('colindex'));
            })
        },
        _leafCols:function(){
            var opts = this.opts;
            var newCols = [];
            var cols = this._expandCols(opts.cols);
            for(var colIndex = 0;colIndex<cols.length;colIndex++){
                var col = cols[colIndex];
                if(!col.cols){
                    newCols.push(col);
                }
            }
            return newCols;
        },
        load:function(args){
            try{
                var opts = this.opts;
                this._hideMessage();
                this._loadCount = this._loadCount + 1;
                if($.isArray(args)){
                    this._loadNative(args)
                }else if(opts.url){
                    this._loadAjax(args);
                }else if(opts.items){

                    this._loadNative(opts.items);
                }else{
                    this._loadNative([])
                }
            }catch(e){
                this._showLoadError();
                throw e;
            }
        },
        _loadNative:function(args){
            this._populate(args);
            this._refreshSortStatus();
        },
        _populate:function(items){
            var opts = this.opts;
            var $body = this.$body;

            this._hideMessage();
            if(items && items.length!==0 && opts.cols){
                var tbodyHtmls = [];
                tbodyHtmls.push('<tbody>');
                for(var rowIndex = 0 ;rowIndex < items.length;rowIndex++){
                    var item = items[rowIndex];
                    tbodyHtmls.push(this._rowHtml(item,rowIndex));
                }
                tbodyHtmls.push('</tbody>');
                $body.empty().html(tbodyHtmls.join(''));
                var $trs = $body.find('tr');
                for(var rowIndex = 0;rowIndex<items.length;rowIndex++){
                    $.data($trs.eq(rowIndex)[0],'item',items[rowIndex]);
                }
            }else{
                this._insertEmptyRow();
                this._showNoData();
            }
            this._setStyle();
            if(opts.fullWidthRows && this._loadCount <=1){
                //this._fullWidthRows();
            }
        },
        _refreshSortStatus:function(){
            var $ths = this.$head.find('th');
            var sortColIndex = -1;
            var sortStatus = '';
            $ths.find('.mmg-title').each(function(index,item){
                var status = $.data(item,'sortStatus');
                if(status){
                    sortColIndex = index;
                    sortStatus = status;
                }
            });
            var sortSatatus = sortSatatus === 'desc' ? 'asc' : 'desc';
            if(sortColIndex>=0){
                $ths.eq(sortColIndex).find('.mmg-title').data('sortStatus',sortSatatus).click();
            }

        },
        _rowHtml:function(item,rowIndex){
            var opts = this.opts;
            var expandCols = this._expandCols(opts.cols);
            var leafCols = this._leafCols();

            if($.isPlainObject(item)){
                var trHtml = [];
                trHtml.push('<tr>');
                for(var colIndex=0; colIndex < leafCols.length; colIndex++){
                    var col = leafCols[colIndex];
                    trHtml.push('<td class="');
                    var index =  $.inArray(col, expandCols);
                    trHtml.push(this._genColClass(index));
                    if(opts.nowrap){
                        trHtml.push(' nowrap');
                    }
                    trHtml.push('"><span class="');
                    if(opts.nowrap){
                        trHtml.push('nowrap');
                    }
                    trHtml.push('">');
                    if(col.renderer){
                        trHtml.push(col.renderer(item[col.name],item,rowIndex));
                    }else{
                        trHtml.push(item[col.name]);
                    }

                    trHtml.push('</span></td>');
                }
                trHtml.push('</tr>');
                return trHtml.join('');
            }
        },
        _setStyle:function(){
            var $head = this.$head;
            var $ths = this._expandThs();
            var $body = this.$body;
            var leafCol = this._leafCols();

            //head
            $ths.eq(0).addClass('first');
            $ths.eq(-1).addClass('last');
            //body
            $body.find('tr,td').removeClass('even')
                .removeClass('colSelected').removeClass('colSelectedEven');

            $body.find('tr:odd').addClass('even');



            var sortIndex = $.inArray($head.find('.mmg-title').filter(function(){
                return $.data(this,'sortStatus') === 'asc' || $(this).data('sortStatus') === 'desc';
            }).parent().parent().data('col'), leafCol);

            $body.find('tr > td:nth-child('+(sortIndex+1)+')').addClass('colSelected')
                .filter(':odd').addClass('colSelectedEven');

            this._resizeHeight();

        },
        _showNoData:function(){
            this._showMessage(this.opts.noDataText);
        },
        _showLoadError:function(){
            this._showMessage(this.opts.loadErrorText);
        },
        _showMessage:function(msg){
            var $mmGrid = this.$mmGrid;
            var $headWrapper = this.$headWrapper;
            var $message = $mmGrid.find('.mmg-message');
            $message.css({
                'left':($mmGrid.width() - $message.width())/2,
                'top':($mmGrid.height() + $headWrapper.height() - $message.height())/2
            }).text(msg).show();
        },
        _hideMessage:function(){
            var $mmGrid = this.$mmGrid;
            $mmGrid.find('.mmg-message').hide();
        },
        resize:function(){
            var opts = this.opts;
            var $mmGrid = this.$mmGrid;
            var $headWrapper = this.$headWrapper;
            var $bodyWrapper = this.$bodyWrapper;

            $mmGrid.width(opts.width);
            if(opts.height!=='auto'){
                $mmGrid.height(opts.height);
                $bodyWrapper.height($mmGrid.height() - $headWrapper.outerHeight(true));
            }

            var $message = $mmGrid.find('.mmg-message');
            if($message.is(":visible")){
                $message.css({
                    'left':($mmGrid.width() - $message.width())/2,
                    'top':($mmGrid.height() + $headWrapper.height() - $message.height())/2
                });
            }

            var $mask = $mmGrid.find('.mmg-mask');
            if($mask.is(':visible')){
                $mask.width($mmGrid.width()).height($mmGrid.height());
                var $loadingWrapper = $mmGrid.find('.mmg-loading');
                $loadingWrapper.css({
                    'left':($mmGrid.width() - $loadingWrapper.width())/2,
                    'top':($mmGrid.height() - $loadingWrapper.height())/2
                })
            }
            $bodyWrapper.trigger('scroll');
            this._resizeHeight();
        },
        _resizeHeight:function(){
            var opts = this.opts;
            var $bodyWrapper = this.$bodyWrapper;
            var $body = this.$body;
            if(opts.height === 'auto'){
                $bodyWrapper.height('auto');
                if($bodyWrapper.width() < $body.width()){
                    $bodyWrapper.height($bodyWrapper.height() + $bodyWrapper.height() - $bodyWrapper[0].clientHeight + 1);
                }
            }
        },
        select:function(args){
            var opts = this.opts;
            var $body = this.$body;
            var $head = this.$head;

            if(typeof args === 'number'){
                var $tr = $body.find('tr').eq(args);
                if(!opts.multiSelect){
                    $body.find('tr:selected').removeClass('selected');
                    if(opts.checkCol){
                        $body.find('tr>td').find('.mmg-check').prop('checked','');
                    }
                }
                if(!$tr.hasClass('selected')){
                    $tr.addClass('selected');
                    if(opts.checkCol){
                        $tr.find('td.mmg-check').prop('checked','checked');
                    }
                }
            }else if(typeof args === 'function'){
                $.each($body.find('tr'),function(index){
                    if(args($.data(this,'item'),index)){
                        var $this = $(this);
                        if(!$this.hasClass('selected')){
                            $this.addClass('selected')
                        }
                        if(opts.checkCol){
                            $this.find('td .mmg-check').prop('checked','checked');
                        }
                    }
                });
            }else if(args === undefined || (typeof args === 'string' && args === 'all')){
                $body.find('tr.selected').removeClass('selected');
                $body.find('tr').addClass('selected');
                $body.find('tr>td').find('.mmg-check').prop('checked','checked');
            }else{
                return;
            }
            if(opts.checkCol){
                var $checks = $body.find('tr>td').find('.mmg-check');
                if($checks.length === $checks.filter(':checked').length){
                    $head.find('th.checkAll').prop('checked','checked');
                }
            }
        },
        deselect:function(args){
            var opts = this.opts;
            var $body = this.$body;
            var $head = this.$head;
            if(typeof args === 'number'){
                $body.find('tr').eq(args).removeClass('selected');
                if(opts.checkCol){
                    $body.find('tr').eq(args).find('td .mmg-checked').prop('checked','');
                }
            }else if(typeof args === 'function'){
                $.each($body.find('tr'),function(index){
                    if(args($.data(this,'item'),index)){
                        $(this).removeClass('selected');
                        if(opts.checkCol){
                            $(this).find('td .mmg-check').prop('checked','');
                        }
                    }
                });
            }else if(args === undefined || (typeof args === 'string' && args === 'all')){
                $body.find('tr.selected').removeClass('selected');
                if(opts.checkCol){
                    $body.find('tr > td').find('.mmg-check').prop('checked','');
                }
            }else{
                return;
            }
            $head.find('th .checkAll').prop('checked','');
        },
        selectedRows:function(){
            var $body = this.$body;
            var selected = [];
            $.each($body.find('tr.selected'),function(index,item){
                selected.push($.data(this,'item'));
            });
            return selected;
        },
        selectedRowsIndex:function(){
            var $body = this.$body;
            var $trs = this.$body.find('tr');
            var selected = [];
            $.each($body.find('tr.selected'),function(index){
                selected.push($trs.index(this));
            });
            return selected;
        },
        rows:function(){
            var $body = this.$body;
            var items = [];
            $.each($body.find('tr'),function(){
                items.push($.data(this,'item'));
            });
            return items;
        },
        row:function(index){
            var $body = this.$body;
            if(index !== undefined && index >= 0){
                var $tr = $body.find('tr').eq(index);
                if($tr.length !== 0){
                    return $.data($tr[0],'item');
                }
            }
        },
        rowsLength:function(){
            var $body = this.$body;
            var length = $body.find('tr').length;
            if(length === 1 && $body.find('tr.emptyRow').length === 1){
                return 0;
            }
            return length;
        },
        addRow:function(item,index){
            var $tbody = this.$body.find('tbody');
            if($.inArray(item)){
                for(var i=item.length -1 ;i>=0;i--){
                    this.addRow(item[i],index);
                }
            }
            if(!$.isPlainObject(item)){
                return;
            }
            this._hideMessage();
            this._removeEmptyRow();
            var $tr;

            if(index === undefined || index < 0){
                $tr = $(this._rowHtml(item,this.rowsLength()));
                $tbody.append($tr);
            }else{
                $tr = $(this._rowHtml(item,index));
                if(index === 0){
                    $tbody.prepend($tr);
                }else{
                    var $before = $tbody.find('tr').eq(index-1);
                    if($before.length === 0){
                        $tbody.append($tr);
                    }else{
                        $before.after($($tr));
                    }
                }
            }
            $tr.data('item',item);
            this._setStyle();
        },
        updateRow:function(item,index){
            var opts = this.opts;
            var $tbody = this.$body.find('tbody');
            if(!$.isPlainObject(item)){
                return;
            }
            var oldItem = this.row(index);
            var $tr = $tbody.find('tr').eq(index);
            var checked = $tr.find('td:first :checkbox').is(':checked');
            $tr.html(this._rowHtml(item,index).slice(4,-5));
            if(opts.checkCol){
                $tr.find('td:first :checkbox').prop('checked',checked);
            }
            $tr.data('item',item);
            this._setStyle();
        },
        removeRow:function(index){
            var that = this;
            var $tbody = that.$body.find('tbody');
            if($.inArray(index)){
                for(var i = index.length-1;i>=0;i--){
                    that.removeRow(index[i]);
                }
                return;
            }

            if(index === undefined){
                var $trs = $tbody.find('tr');
                for(var i = $trs.length - 1;i>=0;i--){
                    that.removeRow(i);
                }
            }else{
                var item = that.row(index);
                $tbody.find('tr').eq(index).remove();
            }
            this._setStyle();
            if(this.rowsLength() === 0){
                this._showNoData();
                this._insertEmptyRow();
            }
        }
    };
    return MMGrid
});
